#version 150 core

uniform sampler2D diffuseTex;
uniform sampler2D depthTex;
uniform vec2 pixelSize;
uniform int isVertical;
uniform int underWater;
uniform float zNear;
uniform float zFar;

in Vertex {
	vec2 texCoord;
	vec4 colour;
} IN;

out vec4 gl_FragColor;
//Technically,thisisn'tquitea'gaussian'distribution...
const float weights[5] = float[](0.12, 0.22, 0.32, 0.22, 0.12);

void main(void) {
	vec2 values[5];
	
	float z = texture2D(depthTex, IN.texCoord.xy).x;
	float depth = ((2.0 * zNear) / (zFar + zNear - (z * (zFar - zNear))));

	depth-=1;
	depth*=1000;
	
	float focalPosition = 0.65;
	float focalDistance = 0.35;
	float tolerance = 1.5;	//Rate of blurryness, smaller means blurs quicker
	float isHDR = 0;
	
	//Distant
	if(depth<=focalPosition-focalDistance){
		//Make values in range 0 to 1
		float distance = clamp((depth)*(tolerance/(focalPosition-focalDistance)), 0.0, 1);
		distance = 1-distance;

		if(isVertical == 1) {
			values = vec2[](vec2(0.0,-pixelSize.y*3),
			vec2(0.0,-pixelSize.y*2), vec2(0.0,pixelSize.y),
			vec2(0.0,pixelSize.y*2), vec2(0.0,pixelSize.y*3));
		}
		else{
			values = vec2[](vec2(-pixelSize.x*3, 0.0),
			vec2(-pixelSize.x*2, 0.0), vec2(pixelSize.x, 0.0),
			vec2(pixelSize.x*2,0.0), vec2(pixelSize.x*3,0.0));
		}
		
		float hdrdistance = clamp(abs(focalPosition-focalDistance-depth)*(1/(focalPosition-focalDistance)+10.0), 0.0, 1.0);
		
		for(int i = 0; i < 5; i++) {
			vec4 tmp = texture2D(diffuseTex , IN.texCoord.xy + values[i]);
			gl_FragColor += tmp * weights[i];
			
			if(depth>0&&tmp.r+tmp.g+tmp.b>(1.7+(hdrdistance/10))){
				isHDR +=weights[i];
			}
		}
		
		vec4 blend = texture2D(diffuseTex, IN.texCoord.xy);
		if(depth>0){
			gl_FragColor = mix(gl_FragColor, blend, cos(distance));
		}else{
			gl_FragColor = mix(gl_FragColor, blend, 1);
		}
		
		if(isHDR>0){			
			gl_FragColor.r=min(gl_FragColor.r+(0.01001*isHDR),1.0);
			gl_FragColor.g=min(gl_FragColor.g+(0.01001*isHDR),1.0);
			gl_FragColor.b=min(gl_FragColor.b+(0.01001*isHDR),1.0);
		}
		
		//Reduce Saturation for distant objects
		float saturation = (gl_FragColor.r+gl_FragColor.g+gl_FragColor.b)/3;
		vec4 grey = vec4(saturation, saturation, saturation, 1.0);
		gl_FragColor = mix(gl_FragColor, grey, sin(distance/20));
		//gl_FragColor = vec4(distance, 0.0, 0.0, 1.0);
	}else if(depth>focalPosition+focalDistance){	//Near
		float distanceToStartOfBlur = (depth-(focalPosition+focalDistance));
		float distance = clamp(distanceToStartOfBlur/tolerance, 0.0, 1);
		
		if(isVertical == 1) {
			values = vec2[](vec2(0.0,-pixelSize.y*3),
			vec2(0.0,-pixelSize.y*2), vec2(0.0,pixelSize.y),
			vec2(0.0,pixelSize.y*2), vec2(0.0,pixelSize.y*3));
		}
		else{
			values = vec2[](vec2(-pixelSize.x*3, 0.0),
			vec2(-pixelSize.x*2, 0.0), vec2(pixelSize.x, 0.0),
			vec2(pixelSize.x*2,0.0), vec2(pixelSize.x*3,0.0));
		}
		isHDR = 0;
		
		vec4 afterBlend = vec4(0,0,0,0);
		for(int i = 0; i < 5; i++) {
			vec4 tmp = texture2D(diffuseTex , IN.texCoord.xy + values[i]);
			afterBlend += tmp * weights[i];
			
			if(depth>0&&tmp.r+tmp.g+tmp.b>1.7){
				isHDR+=weights[i];
			}
			
		}
		
		vec4 blend = texture2D(diffuseTex, IN.texCoord.xy);
		afterBlend = mix(afterBlend, blend, cos(distance));
		
		if(isHDR>0){
			afterBlend.r=min(afterBlend.r+(0.01001*isHDR),1.0);
			afterBlend.g=min(afterBlend.g+(0.01001*isHDR),1.0);
			afterBlend.b=min(afterBlend.b+(0.01001*isHDR),1.0);
		}
		gl_FragColor = afterBlend;
		//gl_FragColor = vec4(isHDR*10, 0.0, 0.0, 1.0);
	}else{	//In focus
		gl_FragColor = texture2D(diffuseTex , IN.texCoord.xy);
		if(isVertical == 1) {
			values = vec2[](vec2(0.0,-pixelSize.y*3),
			vec2(0.0,-pixelSize.y*2), vec2(0.0,pixelSize.y),
			vec2(0.0,pixelSize.y*2), vec2(0.0,pixelSize.y*3));
		}
		else{
			values = vec2[](vec2(-pixelSize.x*3, 0.0),
			vec2(-pixelSize.x*2, 0.0), vec2(pixelSize.x, 0.0),
			vec2(pixelSize.x*2,0.0), vec2(pixelSize.x*3,0.0));
		}

		for(int i = 0; i < 5; i++) {
			vec4 tmp = texture2D(diffuseTex , IN.texCoord.xy + values[i]);
			if(tmp.r+tmp.g+tmp.b>1.7){
				float distance = clamp(abs(focalPosition-depth)*(1/(focalPosition-focalDistance)+0.0), 0.0, 1.0);
				distance = 1;//-distance;
				gl_FragColor.r=min(gl_FragColor.r+(0.0096*distance*weights[i]),1.0);
				gl_FragColor.g=min(gl_FragColor.g+(0.0096*distance*weights[i]),1.0);
				gl_FragColor.b=min(gl_FragColor.b+(0.0096*distance*weights[i]),1.0);
			}
		}
	}
	
}